{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "85ecc545-90c8-4870-b1a0-331383d4b1d1",
   "metadata": {},
   "source": [
    "分组与聚合的原理\n",
    "分组与聚合是数据分析中比较常见的操作，在 Pandas 中，分组是指使用特定的\n",
    "条件将原数据划分为多个组，聚合在这里指的是对每个分组中的数据执行某些\r\n",
    "作（如聚合、转换等），最后将计算的结果进行合\r\n",
    "分组与聚合（ split-apply-combine ）的过程分为三步：\r\n",
    "（1）拆分（ split ）：将数据集按照一些标准拆分为若干个组。\r\n",
    "（2）应用（ apply ）：将某个函数或方法（内置和自定义均可）应到每个分\r\n",
    "组。\r\n",
    "（3）合并（ combine ）：将产生的新值整合到结果对象中。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea379d15-3628-4679-9522-2d9cc04ad2f0",
   "metadata": {},
   "source": [
    "【一、数据分组】\n",
    "通过groupby()方法将数据拆分成组\n",
    "分组聚合的第一个步骤是将数据拆分成组，在 Pandas 中，可以通过groupby()\n",
    "方法将数据集按照某写标准划分为若干个\n",
    "groupby(by=None, axis=0, level=None, as_index=True, \r\n",
    "sort=True,group_keys=True, squeeze=False, observed=False, \r\n",
    "**kwargs)\r\n",
    "参数的含义：\r\n",
    "（1）by：用于确定进行分组的依据\r\n",
    "（2）axis：表示分组轴的方向，可以为0（表示按行）或1（表示按），默认\r\n",
    "为0值\r\n",
    "（3）level：如果某个轴是一个MulitiIndex对象（索引层结构，则会按特定\r\n",
    "几倍或多个级别分组\r\n",
    "（4）as_index：表示聚合后的数据是否以组标签作为索引的DatFrame对象输\r\n",
    "出，接收布尔值，默认为True\r\n",
    "（5）sort：表示是否对分组标签进行排序，接收\n",
    "\n",
    "通过 groupby() 方法执行分组标签进行排序，会返回一个 GroupBy 对象，该对\n",
    "象实际上并没有进行任何计算，只是包含一些关于分组键（比\r\n",
    "df_o['key1']] ）的中间数据而已。一般使用 Series 调用 groupby() 方返\r\n",
    "的是 SeriesGroubBy 对象，而使用 DataFrame 调用 groupby() 方法返的是\r\n",
    "DataFrameBy在进行分组时，可以通过 groupby() 方法的 by 参数来指定按什么标准分组，\n",
    "by 参数可以接收的数据有多种形式，类型也不必相同，分组方式有4种：1、\r\n",
    "列表或数组，其长度必须与待分组的轴一2、样\r\n",
    "DataFrame 对象中某列的3、名称\r\n",
    "字典或 Series 对象，给出待分组轴上的值与分组名称之间的对4、应关系\r\n",
    "函数，用于处理轴索引或索引中的各个标签 对象\r",
    "布尔值，默认为True组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "a75ad4d5-393c-4b3c-b4d0-4f2eb2523282",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  key  data\n",
      "0   C     2\n",
      "1   B     4\n",
      "2   C     6\n",
      "3   A     8\n",
      "4   B    10\n",
      "5   B    12\n",
      "6   A    14\n",
      "7   C    16\n",
      "8   A    18\n",
      "<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000002742FC838C0>\n",
      "('A',   key  data\n",
      "3   A     8\n",
      "6   A    14\n",
      "8   A    18)\n",
      "('B',   key  data\n",
      "1   B     4\n",
      "4   B    10\n",
      "5   B    12)\n",
      "('C',   key  data\n",
      "0   C     2\n",
      "2   C     6\n",
      "7   C    16)\n"
     ]
    }
   ],
   "source": [
    "# 1、通过列名进行分组\n",
    "# 在pandas对象中，如果它的某一列数据满足不同的划分标准，则可以将该列当成分组键来拆分数据集\n",
    "import pandas as pd\n",
    "df = pd.DataFrame({'key':['C','B','C','A','B','B','A','C','A'],\n",
    "                  'data':[2,4,6,8,10,12,14,16,18]})\n",
    "print(df)\n",
    "# 调用groupby（）方法时把列名key传递给by参数，代表key作为分组键，让df对象按照key列进行分组\n",
    "# 按key进行分组\n",
    "print(df.groupby(by='key'))\n",
    "\n",
    "'''\n",
    "从输出的结果可以看出， DataFrame 经过分组后的得到了一个DataFrameGroupBy 对象，该对象是一个可迭代的对\n",
    "象，即只有在真正需要的时候才会执行计算如果要查看每个分组的具体内容，使用 for 循环遍历 DataFrameGroupBy \n",
    "对象\n",
    "'''\n",
    "# 返回的是一个对象，查看对象中的内容\n",
    "group_obj = df.groupby('key')\n",
    "# 遍历分组对象\n",
    "for i in group_obj:\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "f1599d1d-c834-4375-a509-6e18dd48e623",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  key1 key2  data1  data2\n",
      "0    A  one      2      3\n",
      "1    A  two      3      5\n",
      "2    B  one      4      6\n",
      "3    B  two      6      3\n",
      "4    A  one      8      7\n",
      "0    a\n",
      "1    b\n",
      "2    c\n",
      "3    d\n",
      "4    b\n",
      "dtype: object\n",
      "('a',   key1 key2  data1  data2\n",
      "0    A  one      2      3)\n",
      "('b',   key1 key2  data1  data2\n",
      "1    A  two      3      5\n",
      "4    A  one      8      7)\n",
      "('c',   key1 key2  data1  data2\n",
      "2    B  one      4      6)\n",
      "('d',   key1 key2  data1  data2\n",
      "3    B  two      6      3)\n",
      "('a',   key1 key2  data1  data2\n",
      "0    A  one      2      3\n",
      "1    A  two      3      5)\n",
      "('b',   key1 key2  data1  data2\n",
      "2    B  one      4      6)\n"
     ]
    }
   ],
   "source": [
    "# 2.通过Series对象进行分组\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "df = pd.DataFrame({'key1':['A','A','B','B','A'],\n",
    "                  'key2':['one','two','one','two','one'],\n",
    "                  'data1':[2,3,4,6,8],\n",
    "                  'data2':[3,5,6,3,7]})\n",
    "print(df)\n",
    "\n",
    "# 创建一个用做分组键的series对象\n",
    "se = pd.Series(['a','b','c','d','b'])\n",
    "print(se)\n",
    "\n",
    "# 接着，调用groupby方法把se对象传给by参数，将se对象作为分组键拆分df对象\n",
    "# 以得到一个分组对象，遍历该分组对象并查看每个分组的具体内容\n",
    "group_obj = df.groupby(by=se)\n",
    "for i in group_obj:\n",
    "    print(i)\n",
    "\n",
    "# 当serise长度与原数据的索引值的长度不同时\n",
    "se = pd.Series(['a','a','b'])\n",
    "group_obj = df.groupby(se)\n",
    "for i in group_obj:\n",
    "    print(i)\n",
    "'''\n",
    "如果 Series 对象的索引长度与Pandas对象的索引长度不相同时，则只会将部分（具有相同的索引长度）数据进行分组，\n",
    "而不会将全部的数据进行分组\n",
    "\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "7d1e61c8-92c5-4fc0-a67b-e726b9b5ea09",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   a   b   c  d   e\n",
      "0  1   6  11  5  10\n",
      "1  2   7  12  4   9\n",
      "2  3   8  13  3   8\n",
      "3  4   9  14  2   7\n",
      "4  5  10  15  1   6\n",
      "{'a': '第一组', 'b': '第二组', 'c': '第一组', 'd': '第三组', 'e': '第二组'}\n",
      "('第一组',    a   c\n",
      "0  1  11\n",
      "1  2  12\n",
      "2  3  13\n",
      "3  4  14\n",
      "4  5  15)\n",
      "('第三组',    d\n",
      "0  5\n",
      "1  4\n",
      "2  3\n",
      "3  2\n",
      "4  1)\n",
      "('第二组',     b   e\n",
      "0   6  10\n",
      "1   7   9\n",
      "2   8   8\n",
      "3   9   7\n",
      "4  10   6)\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\abc18\\AppData\\Local\\Temp\\ipykernel_16004\\610017568.py:21: FutureWarning: DataFrame.groupby with axis=1 is deprecated. Do `frame.T.groupby(...)` without axis instead.\n",
      "  by_column = num_df.groupby(mapping,axis=1)\n"
     ]
    }
   ],
   "source": [
    "# 3. 通过字典进行分组\n",
    "'''\n",
    "当用字典对 DataFrame 进行分组时，则需要确定轴的方向及字典中的映射关系，即字典中的键为列名，字典的值\n",
    "为自定义的分组名\n",
    "'''\n",
    "import pandas as pd\n",
    "from pandas import DataFrame,Series\n",
    "num_df = DataFrame({'a':[1,2,3,4,5],\n",
    "                   'b':[6,7,8,9,10],\n",
    "                   'c':[11,12,13,14,15],\n",
    "                   'd':[5,4,3,2,1],\n",
    "                   'e':[10,9,8,7,6]})\n",
    "print(num_df)\n",
    "\n",
    "# 创建一个表示分组规则的字典，其中字典的键为num_df对象的列名称，值为自定义的分组名称\n",
    "# 定义分组规则\n",
    "mapping = {'a':'第一组','b':'第二组','c':'第一组','d':'第三组','e':'第二组'}\n",
    "print(mapping)\n",
    "\n",
    "# 接着调用groupby方法，在该方法中传入刚创建的字典，将mapping作为分组键拆分num_df对象\n",
    "by_column = num_df.groupby(mapping,axis=1)\n",
    "for i in by_column:\n",
    "    print(i)\n",
    "\n",
    "'''\n",
    "上述示例拆分 num_df 时，按照横轴的方式进行分组，将a列，c列数据映射到第一组，将b列、e列数据映射到第二组，\n",
    "将d列数据映射到第三组，从输出结果中可以看出， num_df 共分为“第一组” “第二组” “第三组” 三组\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "f3038559-75d1-4d10-ab2b-a83b5953f62b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "       a   b  c\n",
      "sun    1   6  5\n",
      "jack   2   7  4\n",
      "alice  3   8  3\n",
      "helen  4   9  2\n",
      "job    5  10  1\n",
      "(3,      a   b  c\n",
      "sun  1   6  5\n",
      "job  5  10  1)\n",
      "(4,       a  b  c\n",
      "jack  2  7  4)\n",
      "(5,        a  b  c\n",
      "alice  3  8  3\n",
      "helen  4  9  2)\n"
     ]
    }
   ],
   "source": [
    "# 4. 通过函数进行分组\n",
    "''' \n",
    "将函数作为分组键会更加灵活，任何一个被当做分组键的函数都会在各个索引值上被调用一次，返回的值会被用作\n",
    "分组名称。\n",
    "'''\n",
    "import pandas as pd\n",
    "df = DataFrame({'a':[1,2,3,4,5],\n",
    "                'b':[6,7,8,9,10],\n",
    "                'c':[5,4,3,2,1]},index=['sun','jack','alice','helen','job'])\n",
    "print(df)\n",
    "\n",
    "'''\n",
    "如果以行索引名称的长度进行分组，则长度相容的行索引名称会被分为一组，即索引名称长度为3的分为一组，长度为4\n",
    "的分为一组，长度为5的分为一组，共分成三组\n",
    "'''\n",
    "# 使用内置函数len进行分组\n",
    "groupby_obj = df.groupby(len)\n",
    "for i in groupby_obj:\n",
    "    print(i)\n",
    "\n",
    "'''\n",
    "上述示例中，在调用 groupbu() 方法时传入了内置函数 len() ，表明 len() 函数会对行索引一列执行求长度的操作，\n",
    "调用 len 函数返回的长度值作为分组名称，一旦发现索引名称的长度值一样，就归类为一组\n",
    "'''"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1873ccb6-48ba-43ae-8e0c-a2841b26ec8e",
   "metadata": {},
   "source": [
    "案例\r\n",
    "某校学生产生了一个10行10列的数据，请通过4种分组方式，分别对成绩，\r\n",
    "高，排名，竞赛分 进行分组\r\n",
    "1.通过列名进行分组\r\n",
    "2.通过Series对象进行分组\r\n",
    "3.通过字典进行分组\r\n",
    "4.通过数进行分组\r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "421fc381-3372-4283-ad92-766e6d006146",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "通过列名分组的结果：\n",
      "                 成绩     身高    排名   竞赛分   科目一   科目二   科目三   科目四\n",
      "成绩 身高  排名 竞赛分                                                 \n",
      "60 174 10 99   60.0  174.0  10.0  99.0   9.0  94.0  61.0  95.0\n",
      "63 162 10 49   63.0  162.0  10.0  49.0  32.0  60.0  99.0  80.0\n",
      "   174 9  88   63.0  174.0   9.0  88.0  57.0  60.0  61.0  72.0\n",
      "66 187 3  65   66.0  187.0   3.0  65.0  28.0  91.0  74.0  96.0\n",
      "69 188 4  19   69.0  188.0   4.0  19.0  74.0  65.0  98.0  64.0\n",
      "79 189 1  19   79.0  189.0   1.0  19.0  23.0  98.0  71.0  66.0\n",
      "81 173 4  14   81.0  173.0   4.0  14.0  35.0  77.0  78.0  64.0\n",
      "83 167 1  32   83.0  167.0   1.0  32.0  55.0  64.0  60.0  72.0\n",
      "96 174 6  39   96.0  174.0   6.0  39.0  75.0  75.0  87.0  63.0\n",
      "99 151 5  29   99.0  151.0   5.0  29.0  31.0  96.0  95.0  71.0\n",
      "通过series对象分组的结果：\n",
      "           成绩      身高        排名   竞赛分        科目一   科目二        科目三        科目四\n",
      "成绩                                                                          \n",
      "低   66.666667  179.00  6.166667  56.5  37.166667  78.0  77.333333  78.833333\n",
      "高   89.750000  166.25  4.000000  28.5  49.000000  78.0  80.000000  67.500000\n",
      "通过字典进行分组：\n",
      "                          成绩     身高         排名        竞赛分        科目一  \\\n",
      "分组                                                                     \n",
      "成绩低&身高低&排名后五&竞赛一般  63.000000  162.0  10.000000  49.000000  32.000000   \n",
      "成绩低&身高高&排名前五&竞赛一般  71.333333  188.0   2.666667  34.333333  41.666667   \n",
      "成绩低&身高高&排名后五&竞赛优秀  61.500000  174.0   9.500000  93.500000  33.000000   \n",
      "成绩高&身高低&排名前五&竞赛一般  91.000000  159.0   3.000000  30.500000  43.000000   \n",
      "成绩高&身高高&排名前五&竞赛一般  81.000000  173.0   4.000000  14.000000  35.000000   \n",
      "成绩高&身高高&排名后五&竞赛一般  96.000000  174.0   6.000000  39.000000  75.000000   \n",
      "\n",
      "                         科目二   科目三        科目四  \n",
      "分组                                             \n",
      "成绩低&身高低&排名后五&竞赛一般  60.000000  99.0  80.000000  \n",
      "成绩低&身高高&排名前五&竞赛一般  84.666667  81.0  75.333333  \n",
      "成绩低&身高高&排名后五&竞赛优秀  77.000000  61.0  83.500000  \n",
      "成绩高&身高低&排名前五&竞赛一般  80.000000  77.5  71.500000  \n",
      "成绩高&身高高&排名前五&竞赛一般  77.000000  78.0  64.000000  \n",
      "成绩高&身高高&排名后五&竞赛一般  75.000000  87.0  63.000000  \n",
      "通过函数分组：\n",
      "      成绩     身高    排名   竞赛分   科目一   科目二   科目三   科目四\n",
      "分组                                                 \n",
      "A   88.5  173.5   5.0  26.5  55.0  76.0  82.5  63.5\n",
      "B   91.0  159.0   3.0  30.5  43.0  80.0  77.5  71.5\n",
      "C   67.4  182.4   5.4  58.0  38.2  81.6  73.0  78.6\n",
      "D   63.0  162.0  10.0  49.0  32.0  60.0  99.0  80.0\n"
     ]
    }
   ],
   "source": [
    "# coding:UTF-8\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "# 生成数据\n",
    "np.random.seed(0) # 结果重复    生成随机数的种子\n",
    "df = pd.DataFrame({'学号':range(1,11),\n",
    "                  '姓名':[f'学生{i}'for i in range(1,11)],\n",
    "                  '成绩':np.random.randint(60,100,10),\n",
    "                  '身高':np.random.randint(150,190,10),\n",
    "                  '排名':np.random.randint(1,11,10),\n",
    "                  '竞赛分':np.random.randint(0,100,10),\n",
    "                  '科目一':np.random.randint(0,100,10),\n",
    "                  '科目二':np.random.randint(60,100,10),\n",
    "                  '科目三':np.random.randint(60,100,10),\n",
    "                  '科目四':np.random.randint(60,100,10)}) # randint从给定的上下限范围内随机选取整数\n",
    "# 选择只包含数值类型的列\n",
    "numeric_columns = ['成绩','身高','排名','竞赛分','科目一','科目二','科目三','科目四']\n",
    "# 【1、通过列名进行分组】\n",
    "grouped_by_columns = df.groupby(['成绩','身高','排名','竞赛分'])[numeric_columns]\n",
    "mean_by_columns = grouped_by_columns.mean() # 算术平均数  \n",
    "print('通过列名分组的结果：')\n",
    "print(mean_by_columns)\n",
    "\n",
    "\n",
    "# 【2、通过series对象进行分组】\n",
    "series_group = df['成绩'].apply(lambda x:'高' if x > 80 else '低')\n",
    "grouped_by_series = df.groupby(series_group)[numeric_columns]\n",
    "mean_by_series = grouped_by_series.mean()\n",
    "print('通过series对象分组的结果：')\n",
    "print(mean_by_series)\n",
    "\n",
    "\n",
    "# 【3、通过字典进行分组】\n",
    "def create_group(row):\n",
    "    group = []\n",
    "    if row['成绩'] > 80:\n",
    "        group.append('成绩高')\n",
    "    else:\n",
    "        group.append('成绩低')\n",
    "    if row['身高'] >170:\n",
    "        group.append('身高高')\n",
    "    else:\n",
    "        group.append('身高低')\n",
    "    if row['排名'] <= 5:\n",
    "        group.append('排名前五')\n",
    "    else:\n",
    "        group.append('排名后五')\n",
    "    if row['竞赛分'] > 70:\n",
    "        group.append('竞赛优秀')\n",
    "    else:\n",
    "        group.append('竞赛一般')\n",
    "    return '&'.join(group)  # 使用字符串连接各个操作\n",
    "\n",
    "# 创建新的分组列\n",
    "df['分组'] = df.apply(create_group,axis=1)\n",
    "\n",
    "grouped_by_dict = df.groupby('分组')[numeric_columns]\n",
    "mean_by_dict = grouped_by_dict.mean()\n",
    "print('通过字典进行分组：')\n",
    "print(mean_by_dict)\n",
    "\n",
    "\n",
    "# 【4、通过函数进行分组\n",
    "def group_function(row):\n",
    "    if row['成绩'] > 80 and row['身高'] >170:\n",
    "        return 'A'\n",
    "    elif row['成绩'] > 80 and row['身高'] <=170:\n",
    "        return 'B'\n",
    "    elif row['成绩'] <= 80 and row['身高'] >170:\n",
    "        return 'C'\n",
    "    else:\n",
    "        return 'D'\n",
    "# 创建新的分组列\n",
    "df['分组'] = df.apply(group_function,axis=1)\n",
    "grouped_by_function = df.groupby('分组')[numeric_columns]      \n",
    "mean_by_function = grouped_by_function.mean()\n",
    "print('通过函数分组：')\n",
    "print(mean_by_function)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "969051b6-7cd2-488c-8b11-9c3bde313abb",
   "metadata": {},
   "source": [
    "【二、数据聚合】\n",
    "数据聚合，一般是指对分组中的数据执行某些操作，比如求平均值、求最大值\n",
    "等，并且操作后会得到一个结果集，这些实现聚合的操作称为聚合方法\r\n",
    "Pandas中提供了用做聚合操作的 agg() 方法。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "4c51db17-2eee-4440-9199-ce8624072751",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  key1 key2  data1  data2\n",
      "0    A  one      2    3.0\n",
      "1    A  two      3    5.0\n",
      "2    B  one      4    NaN\n",
      "3    B  two      6    3.0\n",
      "4    A  one      8    7.0\n",
      "         data1  data2\n",
      "key1                 \n",
      "A     4.333333    5.0\n",
      "B     5.000000    3.0\n",
      "     key2     data1  data2\n",
      "key1                      \n",
      "A     one  4.333333    5.0\n",
      "B     one  5.000000    3.0\n"
     ]
    }
   ],
   "source": [
    "# 【1】使用内置统计方法聚合数据\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "df = pd.DataFrame({'key1':['A','A','B','B','A'],\n",
    "                  'key2':['one','two','one','two','one'],\n",
    "                  'data1':[2,3,4,6,8],\n",
    "                  'data2':[3,5,np.nan,3,7]})\n",
    "print(df)\n",
    "\n",
    "# 按key1进行分组，并对数据列求平均值\n",
    "df_group_mean = df.groupby('key1').mean(numeric_only=True)\n",
    "print(df_group_mean)\n",
    "\n",
    "'''\n",
    "希望 key2 也参与牟宗形式的聚合，比如计数或取第一个出现的值，那么就需要明确指定使用 agg() 方法\n",
    "来进行复杂的聚合\n",
    "'''\n",
    "# 对不同的列应用不同的聚合函数\n",
    "df_grouped = df.groupby('key1').agg({'key2':'first','data1':'mean','data2':'mean'})\n",
    "print(df_grouped)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8426d195-b2fe-41ea-a1fa-bec9f9f0bacf",
   "metadata": {},
   "source": [
    "【2】面向列的聚合方法\n",
    "当内置方法无法满足聚合要求时，这时可以自定义一个函数，将它传给 agg()\n",
    "方法，实现对 Series 或 DataFrame 对象进行聚合运\n",
    "agg() 方法的语法格式：\n",
    "agg(func,axis=0,*args,**kwargs )\r\n",
    "上述方法中部分参数表示的含义如下：\r\n",
    "(1)func:表示用于汇总数据的函数，可以为单个函数或函数列表。\r\n",
    "(2)axis:表示函数作用于轴的方向，0或index表示将函数应用到每一行1或\r\n",
    "columns表示将函数应用到每一列，该参数的默认\n",
    "需要注意的是，通过agg()方法进行聚合时，func参数既可以接收Pandas中的\n",
    "内置方法，也可以接收自定义的函数，同时，这些方法与函数可以作用于一\r\n",
    "列，也可以将多个函数或方法作用于同一列，还可以将不同函数或方法作用不\r\n",
    "同的列值为0。算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "ca4e82a7-fef8-4aa6-99ed-7c57385fe29f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    a   b   c   d   e   f key\n",
      "0   0   1   2   3   4   5   a\n",
      "1   6   7   8   9  10  11   a\n",
      "2  12  13  14  15  16  17   a\n",
      "3  18  19  20  21  22  23   b\n",
      "4  24  25  26  27  28  29   b\n",
      "5  30  31  32  33  34  35   b\n",
      "    a   b   c   d   e   f key\n",
      "0   0   1   2   3   4   5   a\n",
      "1   6   7   8   9  10  11   a\n",
      "2  12  13  14  15  16  17   a\n",
      "    a   b   c   d   e   f key\n",
      "3  18  19  20  21  22  23   b\n",
      "4  24  25  26  27  28  29   b\n",
      "5  30  31  32  33  34  35   b\n",
      "      a   b   c   d   e   f\n",
      "key                        \n",
      "a    18  21  24  27  30  33\n",
      "b    72  75  78  81  84  87\n",
      "      a   b   c   d   e   f\n",
      "key                        \n",
      "a    12  12  12  12  12  12\n",
      "b    12  12  12  12  12  12\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\abc18\\AppData\\Local\\Temp\\ipykernel_1808\\718011117.py:33: FutureWarning: The provided callable <built-in function sum> is currently using DataFrameGroupBy.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"sum\" instead.\n",
      "  print(data_group.agg(sum))\n"
     ]
    }
   ],
   "source": [
    "# 1.对每一列数据应用同一个函数\n",
    "'''\n",
    "使用 agg() 方法的最简单的方式，就是给该方法的 func 参数传入一个函数，这个函数既可以是内置的，\n",
    "也可以自定义的。\n",
    "'''\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "# 创建一个6*6的dataframe，并用a到f作为列名\n",
    "data_frame = pd.DataFrame(np.arange(36).reshape(6,6),columns=list('abcdef'))\n",
    "\n",
    "# 正确创建表并添加key列\n",
    "data_frame['key'] = pd.Series(list('aaabbb'),name='key')\n",
    "print(data_frame)\n",
    "'''\n",
    "将 data_frame 对象以“key”列为分组键进行分组，凡是该列中数据为“a”的划分为一组，\n",
    "数据为“b”的划分成另外一组，\n",
    "'''\n",
    "data_group = data_frame.groupby('key')\n",
    "#for i in data_group:\n",
    "#    print(i)\n",
    "print(dict([x for x in data_group])['a']) # 输出a组数据信息\n",
    "print(dict([x for x in data_group])['b'])  # 输出b组数据信息\n",
    "'''\n",
    "使用列表推导式遍历分组对象 data_group ,得到的是每个分组的列表，之后将装有分组的列表强转为字典，\n",
    "其中字典中的键为a和b,字典的值为分组的具体内容。通过“字典[组名]”的形式，先查看了a组的数据，再\n",
    "查看了b组的数据\n",
    "'''\n",
    "\n",
    "\n",
    "# 接着可以对每个分组的数据进行聚合运算，如调用agg时传入内置的求和方法sum\n",
    "# 求每个分组的和\n",
    "print(data_group.agg(sum))\n",
    "\n",
    "# 在使用 agg() 方法进行聚合时也可以传入自定义的函数\n",
    "# 定义一个 range_data_group() 函数，用来计算每个分组数据的极差值(极差值=最大值-最小值)\n",
    "def range_data_group(arr):\n",
    "    return arr.max() - arr.min()\n",
    "# 将上述自定义函数作为参数传入到 agg() 方法中\n",
    "print(data_group.agg(range_data_group))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "67b640ec-034d-4b24-8d12-c1dbbe185853",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\abc18\\AppData\\Local\\Temp\\ipykernel_1808\\905793184.py:6: FutureWarning: The provided callable <built-in function sum> is currently using SeriesGroupBy.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"sum\" instead.\n",
      "  data_group.agg([range_data_group,sum])\n",
      "C:\\Users\\abc18\\AppData\\Local\\Temp\\ipykernel_1808\\905793184.py:18: FutureWarning: The provided callable <built-in function sum> is currently using SeriesGroupBy.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string \"sum\" instead.\n",
      "  data_group.agg([('极差',range_data_group),('和',sum)])\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr:last-of-type th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th colspan=\"2\" halign=\"left\">a</th>\n",
       "      <th colspan=\"2\" halign=\"left\">b</th>\n",
       "      <th colspan=\"2\" halign=\"left\">c</th>\n",
       "      <th colspan=\"2\" halign=\"left\">d</th>\n",
       "      <th colspan=\"2\" halign=\"left\">e</th>\n",
       "      <th colspan=\"2\" halign=\"left\">f</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>极差</th>\n",
       "      <th>和</th>\n",
       "      <th>极差</th>\n",
       "      <th>和</th>\n",
       "      <th>极差</th>\n",
       "      <th>和</th>\n",
       "      <th>极差</th>\n",
       "      <th>和</th>\n",
       "      <th>极差</th>\n",
       "      <th>和</th>\n",
       "      <th>极差</th>\n",
       "      <th>和</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>key</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>a</th>\n",
       "      <td>12</td>\n",
       "      <td>18</td>\n",
       "      <td>12</td>\n",
       "      <td>21</td>\n",
       "      <td>12</td>\n",
       "      <td>24</td>\n",
       "      <td>12</td>\n",
       "      <td>27</td>\n",
       "      <td>12</td>\n",
       "      <td>30</td>\n",
       "      <td>12</td>\n",
       "      <td>33</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>b</th>\n",
       "      <td>12</td>\n",
       "      <td>72</td>\n",
       "      <td>12</td>\n",
       "      <td>75</td>\n",
       "      <td>12</td>\n",
       "      <td>78</td>\n",
       "      <td>12</td>\n",
       "      <td>81</td>\n",
       "      <td>12</td>\n",
       "      <td>84</td>\n",
       "      <td>12</td>\n",
       "      <td>87</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      a       b       c       d       e       f    \n",
       "     极差   和  极差   和  极差   和  极差   和  极差   和  极差   和\n",
       "key                                                \n",
       "a    12  18  12  21  12  24  12  27  12  30  12  33\n",
       "b    12  72  12  75  12  78  12  81  12  84  12  87"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 2.对每一列列数据应用不同的函数\n",
    "'''\n",
    "假设现在产生另外一个需求，不仅需要求出每组数据的极差，还需要计算出每组数据的和，即对一列数据使用两种\n",
    "不同的函数\n",
    "'''\n",
    "data_group.agg([range_data_group,sum])\n",
    "# 对象.agg([放置的是自定义的函数求极差，放置的sum函数求和])\n",
    "# 这样它就自动对不同的分组a组和b组，分别求极差值和求和\n",
    "\n",
    "\n",
    "'''\n",
    "函数名经过重命名以后，可以很清晰直观地找到每组数据的极差值以及总和。虽然每一列可以应用不同的函数，\n",
    "但是结果并不能很直观地辨别出每个函数代表的含义。 Pandas 的设计者已经考虑到了这一点，为了能更好地\n",
    "反映出每列对应的数据的信息，可以使用 (name,function) 元组将 function(函数名) 替换为name\n",
    "(自定义名称) 进一步优化内层索引名称\n",
    "\n",
    "'''\n",
    "data_group.agg([('极差',range_data_group),('和',sum)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "2fac6f57-e1b6-4319-9b9f-1f7519e47f7b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>a</th>\n",
       "      <th>b</th>\n",
       "      <th>c</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>key</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>a</th>\n",
       "      <td>18</td>\n",
       "      <td>7.0</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>b</th>\n",
       "      <td>72</td>\n",
       "      <td>25.0</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      a     b   c\n",
       "key              \n",
       "a    18   7.0  12\n",
       "b    72  25.0  12"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 3.对不同列数据应用不同函数\n",
    "'''\n",
    "如果希望对不同的列使用不同的函数，则可以在 agg() 方法中传入一个(“列名”:”函数名”)格式的字典。\n",
    "接下来，在上述示例的基础上，使用字典来聚合datagroup 对象.\n",
    "'''\n",
    "# 每列使用不同的函数聚合分组数据\n",
    "data_group.agg({'a':'sum','b':'mean','c':range_data_group})\n",
    "# 号外号外：自定义函数不需要加引号！！！！\n",
    "# 'a':'sum' a列求和，'b':'mean' b列求平均值，'c':range_data_group c列求极差"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "85334fd3-92fb-4a2a-9439-d0ad2fef13ff",
   "metadata": {},
   "source": [
    "【三、分组级运算】\n",
    "除了前面介绍的聚合操作以外，Pandas还提供了其他操作应用到分组运算中，\n",
    "比如， transform() 和 apply() 方法，它们能够执行更多其他的分组运\n",
    "数据转换\n",
    "前面使用 agg() 方法进行聚合运算时，返回的数据集的形状(shape)与被分组数\n",
    "据集的形状是不同的，如果希望保持与原数据集形状相同，那么可以通\r\n",
    "transfrom() 方法实现。算\r"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa8de9c6-0737-47d0-a5a7-937c7fa36bda",
   "metadata": {},
   "source": [
    "数据转换 \r\n",
    "前面使用 agg() 方法进行聚合运算时，返回的数据集的形状(shape)与被分组\r\n",
    "据集的形状是不同的，如果希望保持与原数据集形状相同，那么可以过\r\n",
    "transfrom() 方法实现。\r\n",
    "transfrom() 方法的语法格式a_group})\r\n",
    "transform(func,*arg\n",
    "上述方法中只有一个 func 参数，表示操作Pandas对象的函数。 transform()\n",
    "方法返回的结果有两种：一种是可以广播的标量值( np.mean )；另一种可以是\r\n",
    "分组大小相同的结果数组通过 transfrom() 方法操作分组时， transfrom() 方法会把 func() 函数应用\n",
    "到各个分组中，并且将结果放在适当的位置上。\r",
    "s,**kwargs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "cf3de087-4ec6-4c59-8912-4e3f42d36839",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    a   b   c   d   e key\n",
      "0   0   1   2   3   4   A\n",
      "1   1   2   3   4   5   A\n",
      "2   6   3   8   9  10   B\n",
      "3  10  11  12  13  14   B\n",
      "4   3   4   4   5   3   B\n",
      ".......................\n",
      "          a    b    c    d    e\n",
      "0  0.500000  1.5  2.5  3.5  4.5\n",
      "1  0.500000  1.5  2.5  3.5  4.5\n",
      "2  6.333333  6.0  8.0  9.0  9.0\n",
      "3  6.333333  6.0  8.0  9.0  9.0\n",
      "4  6.333333  6.0  8.0  9.0  9.0\n",
      "            a    b    c    d    e\n",
      "key                              \n",
      "A    0.500000  1.5  2.5  3.5  4.5\n",
      "B    6.333333  6.0  8.0  9.0  9.0\n"
     ]
    }
   ],
   "source": [
    "# 1、按照图中表格的key列进行分组，可以将表格划分为A、B两组，之后通过transfom方法对这两组执行求平均值的操作。\n",
    "import pandas as pd\n",
    "df = pd.DataFrame({'a':[0,1,6,10,3],\n",
    "                   'b':[1,2,3,11,4],\n",
    "                   'c':[2,3,8,12,4],\n",
    "                   'd':[3,4,9,13,5],\n",
    "                   'e':[4,5,10,14,3],\n",
    "                   'key':['A', 'A', 'B', 'B', 'B']})\n",
    "print(df)\n",
    "print('.......................')\n",
    "\n",
    "# 以key列进行分组，可以将 df 对象拆分成A、B两组，将 mean应用到每个分组中，计算每个分组中每列的平均值\n",
    "data_group = df.groupby('key').transform('mean')\n",
    "print(data_group)\n",
    "\n",
    "data_group = df.groupby('key')\n",
    "a = data_group.mean()\n",
    "print(a)\n",
    "\n",
    "'''\n",
    "从输出结果可以看出，每列的数据是各分组求得的平均数。以A组为例，在A组中a列原来的数据0与1的均值为0.5\n",
    "(0.5为一个标量值),这个均值在A组的a列数据上进行了广播，使得所有A组a列的数据都变成了0.5\n",
    "原始数据的列数与最终结果的列数是不一样的\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c87e7746-6f1b-48dc-9ab1-29c1f1b0c333",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   A  B  C   D\n",
      "0  2  4  9   3\n",
      "1  3  3  7   4\n",
      "2  3  3  0   8\n",
      "3  4  6  7   6\n",
      "4  2  6  8  10\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>A</th>\n",
       "      <th>B</th>\n",
       "      <th>C</th>\n",
       "      <th>D</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2.5</td>\n",
       "      <td>3.5</td>\n",
       "      <td>8.0</td>\n",
       "      <td>3.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2.5</td>\n",
       "      <td>3.5</td>\n",
       "      <td>8.0</td>\n",
       "      <td>3.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3.0</td>\n",
       "      <td>5.0</td>\n",
       "      <td>5.0</td>\n",
       "      <td>8.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3.0</td>\n",
       "      <td>5.0</td>\n",
       "      <td>5.0</td>\n",
       "      <td>8.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>3.0</td>\n",
       "      <td>5.0</td>\n",
       "      <td>5.0</td>\n",
       "      <td>8.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     A    B    C    D\n",
       "0  2.5  3.5  8.0  3.5\n",
       "1  2.5  3.5  8.0  3.5\n",
       "2  3.0  5.0  5.0  8.0\n",
       "3  3.0  5.0  5.0  8.0\n",
       "4  3.0  5.0  5.0  8.0"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'''\n",
    "如果希望图中的表格进行转换后，返回具有相同形状的结果，那么可以创建一个Series 对象，该对象的长度与表格中\n",
    "的行数是相同的，按照这个 Series 对象进行分组，便可以得到一个形状相同的对象。\n",
    "'''\n",
    "import pandas as pd\n",
    "df = pd.DataFrame({'A':[2,3,3,4,2],\n",
    "                   'B':[4,3,3,6,6],\n",
    "                   'C':[9,7,0,7,8],\n",
    "                   'D':[3,4,8,6,10]})\n",
    "print(df)\n",
    "# 创建一个列表key,key的长度需要与 df 对象的行数是一样的，我们把key当做分组键，将 df 对象按照key列表进行分组\n",
    "# 以key为分组依据，对df对象进行分组\n",
    "key = ['one','one','two','two','two']\n",
    "df.groupby(key).transform('mean')  # 我感觉也是内置函数\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "d6e6739b-dc11-4d8a-9215-9027f2b51cbe",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   A  B  C   D\n",
      "0  2  4  9   3\n",
      "1  3  3  7   4\n",
      "2  3  3  0   8\n",
      "3  4  6  7   6\n",
      "4  2  6  8  10\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>A</th>\n",
       "      <th>B</th>\n",
       "      <th>C</th>\n",
       "      <th>D</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "      <td>8</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "      <td>8</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "      <td>8</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   A  B  C  D\n",
       "0  1  1  2  1\n",
       "1  1  1  2  1\n",
       "2  2  3  8  4\n",
       "3  2  3  8  4\n",
       "4  2  3  8  4"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "df = pd.DataFrame({'A':[2,3,3,4,2],\n",
    "                   'B':[4,3,3,6,6],\n",
    "                   'C':[9,7,0,7,8],\n",
    "                   'D':[3,4,8,6,10]})\n",
    "print(df)\n",
    "\n",
    "def range_data_group(arr):\n",
    "    return arr.max() - arr.min()\n",
    "\n",
    "key = ['one','one','two','two','two']\n",
    "df.groupby(key).transform(range_data_group) # 自定义函数的方式"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "25d800a2-5fcb-47f1-83d7-c2b980af50dd",
   "metadata": {},
   "source": [
    "2、数据应用\n",
    "当某些分组操作，既不适合使用 agg() 方法进行聚合，也不适合使用\n",
    "transform() 方法进行转换时，便可以让 apply (方法排上用场了。 apply() \r\n",
    "法的使用十分灵活，它可以作用于 DataFrame 中每一行、每一列元素，它可\r\n",
    "以在许多标准用例中替代聚合和转换。\r"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cfa12455-cb34-430e-8cd7-872807c97d7c",
   "metadata": {},
   "source": [
    "apply(func,axis=0,broadcast=None,raw=False,reduce=None,result_\n",
    "type=None,args=(),**kwds)\r\n",
    "上述方法中常用参数表示的含义如下：\r\n",
    "(1)func:表示应用于某一行或某一列的函数。\r\n",
    "(2)axis:表示函数操作的轴向，“0”或“index”表示将函数用于行\r\n",
    "上，“1”或“columns”表示将函数应用于列上，默认为0。\r\n",
    "(3)broadeast:表示是否将数据进行广播。若设为False或None,会返回一个\r\n",
    "Series对象，其长度跟索引的长度或列数一样；若设为True,则示结果将被广\r\n",
    "播到原始对象中，原始的索引和列将会被保留。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9db5923f-dc1e-4c2c-a3b8-9d8c38258974",
   "metadata": {},
   "source": [
    "假设现在有一个10行4列的表格，从左边数表格中前3列的数据都是数值类型\n",
    "的，最后一列的数据是字符串类型\n",
    "在图中的表格中，按照key一列的数据进行分组，将表格拆分成a、b两组，将\n",
    "max() 方法作用于每个分组中，求出每个分组中的最大值。\r",
    "的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "c06901cf-0b47-45ea-bfad-44183f7b15ae",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   data1  data2  data3 key\n",
      "0     80     41     30   b\n",
      "1     23     87     78   a\n",
      "2     25     58     23   a\n",
      "3     63     68     66   b\n",
      "4     94     72     16   b\n",
      "5     92     89     59   a\n",
      "6     99     60     20   b\n",
      "7     92     42     23   a\n",
      "8     82     53     24   a\n",
      "9     99     65     40   a\n",
      "<pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000026C37E08C80>\n",
      "('a',    data1  data2  data3 key\n",
      "1     23     87     78   a\n",
      "2     25     58     23   a\n",
      "5     92     89     59   a\n",
      "7     92     42     23   a\n",
      "8     82     53     24   a\n",
      "9     99     65     40   a)\n",
      "('b',    data1  data2  data3 key\n",
      "0     80     41     30   b\n",
      "3     63     68     66   b\n",
      "4     94     72     16   b\n",
      "6     99     60     20   b)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>data1</th>\n",
       "      <th>data2</th>\n",
       "      <th>data3</th>\n",
       "      <th>key</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>23</td>\n",
       "      <td>87</td>\n",
       "      <td>78</td>\n",
       "      <td>a</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>25</td>\n",
       "      <td>58</td>\n",
       "      <td>23</td>\n",
       "      <td>a</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>92</td>\n",
       "      <td>89</td>\n",
       "      <td>59</td>\n",
       "      <td>a</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>92</td>\n",
       "      <td>42</td>\n",
       "      <td>23</td>\n",
       "      <td>a</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>82</td>\n",
       "      <td>53</td>\n",
       "      <td>24</td>\n",
       "      <td>a</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>99</td>\n",
       "      <td>65</td>\n",
       "      <td>40</td>\n",
       "      <td>a</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   data1  data2  data3 key\n",
       "1     23     87     78   a\n",
       "2     25     58     23   a\n",
       "5     92     89     59   a\n",
       "7     92     42     23   a\n",
       "8     82     53     24   a\n",
       "9     99     65     40   a"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from pandas import DataFrame, Series\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "data_frame = DataFrame({'data1':\n",
    "[80,23,25,63,94,92,99,92,82,99],\n",
    "'data2':\n",
    "[41,87,58,68,72,89,60,42,53,65],\n",
    "'data3':\n",
    "[30,78,23,66,16,59,20,23,24,40],\n",
    "'key':list('baabbabaaa')})\n",
    "print(data_frame)\n",
    "\n",
    "# 对数据进行分组\n",
    "data_by_group = data_frame.groupby('key')\n",
    "print(data_by_group)\n",
    "for i in data_by_group:\n",
    "    print(i)\n",
    "\n",
    "# 打印分组数据\n",
    "dict([x for x in data_by_group])['a']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "413b4556-cec4-413b-bbb9-71ce125813ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "感觉不全"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
